/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.mes.controller;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.base.domain.req.GetGoodsRequest;
import com.xy.biz.base.domain.req.ListDictItemRequest;
import com.xy.biz.base.domain.resp.ListDictItemResponse;
import com.xy.biz.mes.client.ManufactureOrderClient;
import com.xy.biz.mes.domain.converter.ManufactureOrderConverter;
import com.xy.biz.mes.domain.enums.ManufactureGoodsTypeEnum;
import com.xy.biz.mes.domain.enums.ManufactureOrderStatusEnum;
import com.xy.biz.mes.domain.enums.ManufactureOrderTypeEnum;
import com.xy.biz.mes.domain.enums.ManufactureTaskStatusEnum;
import com.xy.biz.mes.domain.query.ManufactureOrderQuery;
import com.xy.biz.mes.domain.req.GetManufactureOrderRequest;
import com.xy.biz.mes.domain.req.ListManufactureOrderRequest;
import com.xy.biz.mes.domain.req.SaveManufactureOrderRequest;
import com.xy.biz.mes.domain.resp.GetManufactureOrderResponse;
import com.xy.biz.mes.service.ManufactureOrderService;
import com.xy.biz.rs.domain.enums.ReconstitutionStatusEnum;
import com.xy.biz.rs.domain.enums.SplitGoodsTypeEnum;
import com.xy.lang.domain.KeyValue;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.tuples.Triple;
import com.xy.lang.util.EnumUtils;
import com.xy.lang.util.ResultUtils;
import com.xy.lang.validation.SaveChecks;
import com.xy.lang.validation.UpdateChecks;
import com.xy.lang.validation.annotation.Validatable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author zsp
 * @date 2022-1-6
 */
@Slf4j
@RestController
@RequestMapping("/api/mes/order")
public class ManufactureOrderController implements ManufactureOrderClient {

    @Autowired
    private ManufactureOrderService manufactureOrderService;
    @Autowired
    private DictClient dictClient;

    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save")
    public Result<?> saveManufactureOrder(@RequestBody SaveManufactureOrderRequest request) {
        if (CollectionUtils.isEmpty(request.getGoodsList())) {
            return Result.ofBadRequest("缺少货品明细");
        }
        return manufactureOrderService.saveManufactureOrder(request);
    }

    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save_all")
    public Result<?> saveAllManufactureOrder(@RequestBody Collection<SaveManufactureOrderRequest> collection) {
        if (collection.stream().anyMatch(e -> CollectionUtils.isEmpty(e.getGoodsList()))) {
            return Result.ofBadRequest("缺少货品明细");
        }
        return manufactureOrderService.saveAllManufactureOrder(collection);
    }

    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/update")
    public Result<?> updateManufactureOrder(@RequestBody SaveManufactureOrderRequest request) {
        return manufactureOrderService.updateManufactureOrder(ManufactureOrderConverter.toBO(request));
    }

    @Validatable
    @PostMapping(value = "/delete")
    public Result<?> deleteManufactureOrder(@RequestBody GetManufactureOrderRequest request) {
        return manufactureOrderService.deleteManufactureOrder(request.getManufactureOrderId());
    }

    @Validatable
    @PostMapping(value = "/get")
    @Override
    public Result<GetManufactureOrderResponse> getManufactureOrder(@RequestBody GetManufactureOrderRequest request) {
        return Result.success(ManufactureOrderConverter.toResponse(manufactureOrderService.getManufactureOrder(request.getManufactureOrderId())));
    }

    @Validatable
    @PostMapping(value = "/get_bom_technique_template")
    public Result<Triple<Long, Long, Long>> getBomAndTechniqueAndTemplate(@RequestBody GetGoodsRequest request) {
        return Result.success(manufactureOrderService.getBomAndTechniqueAndTemplate(request.getGoodsId()));
    }

    @PostMapping(value = "/list_by_ids")
    @Override
    public Result<List<GetManufactureOrderResponse>> listManufactureOrderById(@RequestBody Collection<Long> collection) {
        return Result.success(ManufactureOrderConverter.toResponse(manufactureOrderService.listManufactureOrderById(collection, true)));
    }

    @PostMapping(value = "/list")
    @Override
    public Result<List<GetManufactureOrderResponse>> listManufactureOrder(@RequestBody ListManufactureOrderRequest request) {
        return Result.success(ManufactureOrderConverter.toResponse(manufactureOrderService.listManufactureOrder(ManufactureOrderConverter.toQuery(request))));
    }

    @PostMapping(value = "/count")
    @Override
    public Result<Integer> countManufactureOrder(@RequestBody ListManufactureOrderRequest request) {
        return Result.success(manufactureOrderService.countManufactureOrder(ManufactureOrderConverter.toQuery(request)));
    }

    @PostMapping(value = "/page")
    @Override
    public Result<Page<GetManufactureOrderResponse>> pageManufactureOrder(@RequestBody ListManufactureOrderRequest request) {
        ManufactureOrderQuery query = ManufactureOrderConverter.toQuery(request);
        List<GetManufactureOrderResponse> list = ManufactureOrderConverter.toResponse(manufactureOrderService.listManufactureOrder(query));
        int count = manufactureOrderService.countManufactureOrder(query);
        return Result.success(new Page<>(list, count));
    }

    @GetMapping(value = "/list_pre_options")
    public Result<Map<String, List>> listPreOptions() {
        Map<String, List> map = new HashMap<>();
        map.put("orderStatus", EnumUtils.toKeyValueList(ManufactureOrderStatusEnum.values(),
                (e) -> ((ManufactureOrderStatusEnum) e).getName()));
        map.put("orderType", EnumUtils.toKeyValueList(ManufactureOrderTypeEnum.values(),
                (e) -> ((ManufactureOrderTypeEnum) e).getName()));
        map.put("reconstitutionStatus", EnumUtils.toKeyValueList(ReconstitutionStatusEnum.values(),
                (e) -> ((ReconstitutionStatusEnum) e).getName()));
        map.put("manufactureGoodsType", EnumUtils.toKeyValueList(ManufactureGoodsTypeEnum.values(),
                (e) -> ((ManufactureGoodsTypeEnum) e).getName()));
        map.put("splitGoodsType", EnumUtils.toKeyValueList(SplitGoodsTypeEnum.values(),
                (e) -> ((SplitGoodsTypeEnum) e).getName()));
        map.put("taskStatus", EnumUtils.toKeyValueList(ManufactureTaskStatusEnum.values(),
                (e) -> ((ManufactureTaskStatusEnum) e).getName()));
        List<ListDictItemResponse> dictList = ResultUtils.get(dictClient.listDictItem(
                ListDictItemRequest.builder().pageSize(1000).dictGroupCodes(
                        Arrays.asList("manufacture_order_tag", "goods_unit", "goods_quality_setting","weight_unit"))
                        .build()));
        if (!CollectionUtils.isEmpty(dictList)) {
            List<KeyValue<String, String>> inboundOrderTagList = new ArrayList<>();
            List<KeyValue<String, String>> goodsUnitList = new ArrayList<>();
            List<KeyValue<String, String>> goodsQualitySettingList = new ArrayList<>();
            List<KeyValue<String, String>> weightUnitList = new ArrayList<>();
            dictList.forEach(e -> {
                if ("manufacture_order_tag".equals(e.getDictGroupCode())) {
                    inboundOrderTagList.add(new KeyValue<>(e.getDictCode(), e.getDictValue()));
                } else if ("goods_unit".equals(e.getDictGroupCode())) {
                    goodsUnitList.add(new KeyValue<>(e.getDictCode(), e.getDictValue()));
                } else if ("goods_quality_setting".equals(e.getDictGroupCode())) {
                    goodsQualitySettingList.add(new KeyValue<>(e.getDictCode(), e.getDictValue()));
                } else if ("weight_unit".equals(e.getDictGroupCode())) {
                    weightUnitList.add(new KeyValue<>(e.getDictCode(), e.getDictValue()));
                }
            });
            map.put("manufactureOrderTag", inboundOrderTagList);
            map.put("goodsUnit", goodsUnitList);
            map.put("goodsQualitySetting", goodsQualitySettingList);
            map.put("weightUnit", weightUnitList);
        }
        return Result.success(map);
    }

}
